use chrono::Utc;
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};

/// JWT 的声明体结构体，包含用户身份和令牌元数据
/// 
/// @author 张翔宇
/// @since 2025年7月1日
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Claims {
    /// 用户ID
    pub sub: i64,
    /// 用户角色列表
    pub roles: Vec<String>,
    /// 过期时间（Unix 时间戳，单位秒）
    pub exp: i64,
    /// 签发时间（Unix 时间戳，单位秒）
    pub iat: i64
}

impl Claims {
    /// 创建新的 Claims 实例
    /// 
    /// # 参数
    /// * `user_id` - 用户ID
    /// * `roles` - 用户角色列表
    /// * `base` - 配置，包含 JWT 过期时间
    /// 
    /// # 返回
    /// 返回一个 Claims 结构体实例
    pub fn new(user_id: i64, expiration: &i64, roles: Vec<String>) -> Self {
        let iat = Utc::now().timestamp(); // 当前时间戳
        let exp = iat + expiration; // 过期时间

        Claims {
            sub: user_id,
            roles,
            exp,
            iat
        }
    }

    // /// 判断用户是否拥有指定角色
    // /// 
    // /// # 参数
    // /// * `role` - 需要检查的角色名
    // /// 
    // /// # 返回
    // /// 如果拥有该角色返回 true，否则返回 false
    // pub fn has_role(&self, role: &str) -> bool {
    //     self.roles.iter().any(|r| r == role)
    // }
}

/// 创建 JWT 字符串
/// 
/// # 参数
/// * `claims` - 需要编码的声明体
/// * `base` - 配置，包含 JWT 密钥
/// 
/// # 返回
/// 返回编码后的 JWT 字符串或错误
pub fn create_jwt(claims: &Claims, secret: &str) -> Result<String, jsonwebtoken::errors::Error> {
    encode(
        &Header::default(), 
        claims, 
        &EncodingKey::from_secret(secret.as_ref()),
    )
}

/// 解码并验证 JWT 字符串
/// 
/// # 参数
/// * `token` - 需要解码的 JWT 字符串
/// * `base` - 配置，包含 JWT 密钥
/// 
/// # 返回
/// 返回解码后的 Claims 或错误
pub fn decode_jwt(token: &str, secret: &str) -> Result<Claims, jsonwebtoken::errors::Error> {
    let token_data = decode::<Claims>(
        token,
        &DecodingKey::from_secret(secret.as_ref()),
        &Validation::default()
    )?;

    Ok(token_data.claims)
}

// /// JWT 认证相关中间件
// /// 
// /// @author 张翔宇
// /// @since 2025年7月1日
// pub struct JwtMiddleware;
// 
// impl JwtMiddleware {
//     /// 检查用户是否拥有指定角色的中间件
//     ///
//     /// # 参数
//     /// * `role` - 需要检查的角色名
//     ///
//     /// # 返回
//     /// 返回一个闭包，接收 HttpRequest，若拥有角色返回 Ok，否则返回 Forbidden 或 Unauthorized
//     pub fn require_role(role: &'static str) -> impl Fn(&actix_web::HttpRequest) -> Result<(), AppError> + Clone {
//         move |req: &actix_web::HttpRequest| {
//             // 从请求扩展中获取 Claims
//             if let Some(claims) = req.extensions().get::<Claims>() {
//                 if claims.has_role(role) {
//                     Ok(())
//                 } else {
//                     Err(AppError::Forbidden(format!("需要 {} 角色", role)))
//                 }
//             } else {
//                 Err(AppError::Unauthorized)
//             }
//         }
//     }
// }